home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
fish
/
001-100
/
001-025
/
020
/
pack
/
wildexp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-17
|
9KB
|
292 lines
/*
** The following module contains functions which permit wildcard
** filename expansion using Unix type wildcard characters. This
** module can be compiled separately and included in the link for
** any programs which desire it's support. The following functions
** are present:
**
** findfirst - find the first occurance of a file matching
** the given name which may contain Unix style
** wildcards.
** findnext - find the next occurance of a file. Returns
** 0 if no more matches remain.
** find_cleanup - release all storage and locks reserved by findfirst
** and/or findnext. MUST be called before exit!
** fferror - given an error code returned by findnext, this
** function returns a pointer to a descriptive
** error message string.
** iswild - given a string, this function returns
** TRUE if the string contains a wildcard character
** and FALSE if not.
** wildexp - given a file name and a pointer to a table of
** pointers, this function will fill the table
** with a list of file names in the indicated
** directory which match the given name.
**
**
** Written by: Rick Schaeffer
** E. 13611 26th Ave.
** Spokane, Wa. 99216
** Compuserve ID: 70120,174
** Bytenet ID: ricks.
*/
#include "wildexp.h"
/*
** Return values for findfirst and findnext are:
** 0 = retval ok, find struct "fname" contains name of file found
** 1 = file name too long
** 2 = error in parsing
** 3 = invalid path name
** 4 = first Examine failed
** 5 = not a directory
*/
/* fferror -- return a meaningful error message for findxxx errors
** Parameter:
** errcd - An integer containing the error code returned by findfirst
** or findnext.
**
** Returns:
** msgptr - A pointer to a meaningful error message
*/
char *fferror(errcd)
int errcd;
{
static char *errmsg[] = {
"Filename too long",
"Filename invalid",
"Pathname invalid",
"Examine failed",
"Pathname invalid",
"Error code invalid"
};
if (--errcd > 4)
errcd = 5;
return(errmsg[errcd]);
}
/* findfirst -- find the first occurance of a given file name in either
** the given or the current directory.
** Parameters:
** name - A pointer to a filename string. May contain wildcard
** characters ('?' and/or '*'). May optionally contain
** a directory path. Example: "df0:c/d*" matches all
** files in directory "df0:c" which begin with the letter
** "d".
** fwk - A pointer to a structure which will be filled in by
** findfirst and used by findnext. Must NOT be disturbed
** between calls!
**
** Returns:
** 0 = successful completion. fwk filled in with first matching
** file.
** >0 = error code. use fferror to obtain a meaningful description.
**
** Example:
** findfirst("*.c",fwk)
** The first matching file is in fwk->fname.
*/
findfirst(name,fwk)
char *name;
struct find *fwk;
{
struct Process *tp,*FindTask();
int pt[16];
int last;
char *p1,*strchr();
fwk->fp = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock),0);
/* caller must free this space! */
fwk->flock = 0;
if (strlen(name) > 128)
return(1); /* file name too long */
if ((p1 = strchr(name,':')) != NULL)
if (strchr(name,'/') == NULL) {
*p1 = 0;
strcpy(fwk->path,name);
strcat(fwk->path,":/");
strcat(fwk->path,p1+1);
strcpy(name,fwk->path);
}
strcpy(fwk->path,name);
if (stspfp(name,pt) == -1)
return(2); /* error in parsing */
for (last=0; last < 16; last++)
if (pt[last] == -1)
break;
last--; /* now points at file name portion */
if ((last == 0) && (pt[0] == 0)) { /* no path */
if (strlen(name) > 32)
return(1); /* file name too long */
strcpy(fwk->name,name);
fwk->path[0] = 0;
tp = FindTask(NULL);
fwk->flock = DupLock(tp->pr_CurrentDir);
bldfull(fwk); /* build full path name */
}
else {
if (strlen(&name[pt[last]]) > 32)
return(1); /* file name too long */
strcpy(fwk->name,&name[pt[last]]);
fwk->path[pt[last] - 1] = 0;
if ((fwk->flock = Lock(fwk->path,ACCESS_READ)) == 0)
return(3); /* invalid path name */
bldfull(fwk);
}
if (Examine(fwk->flock,fwk->fp)) { /* get directory name */
if (fwk->fp->fib_DirEntryType > 0)
return(findnext(fwk));
else
return(5); /* not a directory */
}
else
return(4); /* first examine failed */
}
/*
** findnext -- find next occurance of a matching file.
** Parameter:
** fwk - pointer to a "find" structure which has been filled in
** by a call to findfirst.
**
** Returns:
** 0 = Match found. fwk->fname contains the name.
** -1 = No more matches.
*/
int findnext(fwk)
struct find *fwk;
{
while (ExNext(fwk->flock,fwk->fp)) {
strcpy(fwk->fname,fwk->fp->fib_FileName);
if (fnmatch(fwk->fname,fwk->name))
return(0);
}
return(-1);
}
bldfull()
{
}
/* find_cleanup -- release any structures and locks used by findfirst.
** Parameters:
** fwk - pointer to a "find" structure which has been previously
** filled in by findfirst.
** Returns:
** nothing
*/
find_cleanup(fwk)
struct find *fwk;
{
if (fwk->flock)
UnLock(fwk->flock);
if (fwk->fp)
FreeMem(fwk->fp,sizeof(struct FileInfoBlock));
}
/* fnmatch -- perform unix style pattern match on a file name
** usage: result = fnmatch(name,pattern)
** returns 1 if "name" matches "pattern", 0 otherwise
*/
int fnmatch(name,pattern)
register char *name,*pattern;
{
while (*pattern) {
if (*pattern == '*') {
while (*pattern == '*')
pattern++;
while ((*name) && (tolower(*name) != tolower(*pattern)))
name++;
if (*name == 0)
if (*pattern == 0)
return(1); /* matched */
else
return(0);
}
if (*pattern == '?') {
pattern++;
name++;
continue;
}
if (tolower(*pattern) != tolower(*name))
return(0); /* not matched */
pattern++;
name++;
}
if ((*name == 0) && (*pattern == 0))
return(1); /* matched */
else
return(0); /* not matched */
}
/*
** wildexp -- expand a wildcard file name
** Parameters:
** name - Pointer to the file name to be expanded.
** adtbl - Pointer to an array of pointers.
** maxargs - The maximum number of pointers contained in adtbl.
**
** Returns:
** 1 = Successful completion. The adtbl array will contain pointers
** to all file names found and will be terminated with a NULL
** pointer. It's use is exactly like use of the standard C
** argv array except that the first filename argument is in
** adtbl[0] whereas argv[0] contains a pointer to the name of
** the function which was invoked.
** 0 = An error occured.
*/
int wildexp(name,adtbl,maxargs)
char *name;
register char **adtbl;
int maxargs;
{
struct find f;
register int i=0;
char *malloc();
int retval;
if ((retval = findfirst(name,&f)) > 0) {
*adtbl = NULL;
find_cleanup(&f);
return(0);
}
while (retval == 0) {
if (f.fp->fib_DirEntryType > 0) {
retval=findnext(&f);
continue; /* it's a directory */
}
*adtbl = malloc(strlen(f.path)+strlen(f.fname)+1);
if (*adtbl == NULL) {
find_cleanup(&f);
return(0); /* arena is full */
}
strcpy(*adtbl,f.path);
if ((f.path[0] != 0) && (f.path[strlen(f.path)-1] != ':'))
strcat(*adtbl,"/");
strcat(*adtbl++,f.fname);
if ((++i) >= maxargs)
return(0);
retval=findnext(&f);
}
*adtbl = NULL;
find_cleanup(&f);
return(1);
}
int iswild(s)
char *s;
{
while (*s) {
if ((*s == '*') || (*s == '?'))
return(1);
s++;
}
return(0);
}